﻿/*
  Copyright (C) 2005-2012 Govert van Drimmelen

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.


  Govert van Drimmelen
  govert@icon.co.za
*/

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

namespace ExcelDna.Integration.Rtd
{  
    // Pushes data to Excel via the RTD topic.
    internal class ExcelRtdObserver : IExcelObserver
    {
        readonly ExcelRtdServer.Topic _topic;

        // Indicates whether the RTD Topic should be shut down
        // Set to true if the work is completed or if an error is signalled.
        public bool IsCompleted { get; private set; }
        public object Value { get; private set; } // Keeping our own value, since the RTD Topic.Value is insufficient (e.g. string length limitation)

        internal ExcelRtdObserver(ExcelRtdServer.Topic topic)
        {
            _topic = topic;
            Value = ExcelError.ExcelErrorNA;
        }

        public void OnCompleted()
        {
            IsCompleted = true;
            // Force another update to ensure DisconnectData is called.
            // CONSIDER: Do we need to UpdateNotify here?
            //           Not necessarily. Next recalc will call the function, not call RTD and that will trigger DisconnectData.
            _topic.UpdateNotify();
        }

        public void OnError(Exception exception)
        {
            // TODO: Is the sequence here important?
            Value = ExcelIntegration.HandleUnhandledException(exception);
            // Set the topic value to #VALUE (not used!?) - converted to COM code in Topic
            _topic.UpdateValue(ExcelError.ExcelErrorValue);
            IsCompleted = true;
        }

        public void OnNext(object value)
        {
            Value = value;
            // Not actually setting the topic value, just poking it
            // TODO: Using the 'fake' RTD value should be optional - to give us a way to deal with 'newValues' one day.
            _topic.UpdateValue(DateTime.UtcNow.ToOADate());
        }
    }
    
}